package com.basker.pisces.springcloud.config;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import com.basker.pisces.springcloud.context.LoginContextInterceptor;
import com.basker.pisces.springcloud.locale.ServiceLocaleInterceptor;
import com.basker.pisces.springcloud.rpc.ServiceRpcContexctInterceptor;
import com.basker.pisces.springcloud.trace.ServiceTraceContextInterceptor;

/**
 * 默认的WebMvcConfigurer，设置和springmvc相关的组件
 *
 * @author hangwen
 * @see ServiceLocaleInterceptor
 */
@Configuration
public class DefaultWebMvcConfigurer implements WebMvcConfigurer {

    @Autowired
    private BeanFactory beanFactory;

    /**
     * 添加设置Local的拦截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        if (this.beanFactory.containsBean("loginContextInterceptor")) {
            LoginContextInterceptor loginContextInterceptor = this.beanFactory.getBean(LoginContextInterceptor.class);
            registry.addInterceptor(loginContextInterceptor);
        }

        if (this.beanFactory.containsBean("serviceRpcContexctInterceptor")) {
            ServiceRpcContexctInterceptor serviceRpcContexctInterceptor = this.beanFactory
                    .getBean(ServiceRpcContexctInterceptor.class);
            registry.addInterceptor(serviceRpcContexctInterceptor);
        }

        registry.addInterceptor(traceContextInterceptor());
        registry.addInterceptor(serviceLocaleInterceptor());
    }

    /**
     * feignWebRegistrations提供一个排除{@link FeignClient}注解的{@link RequestMappingHandlerMapping}
     *
     * @return
     */
    @Bean
    public WebMvcRegistrations feignWebRegistrations() {
        return new WebMvcRegistrations() {
            @Override
            public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
                return new FeignClinetExcludeMappingHandlerMapping();
            }
        };
    }

    @Bean
    @ConditionalOnProperty(name = "pisces.web.loginContext.validate.enable", matchIfMissing = true)
    public LoginContextInterceptor loginContextInterceptor() {
        return new LoginContextInterceptor();
    }

    @Bean
    public ServiceLocaleInterceptor serviceLocaleInterceptor() {
        return new ServiceLocaleInterceptor();
    }

    @Bean
    @ConditionalOnProperty(name = "pisces.web.rpcContext.validate.enable", matchIfMissing = false)
    public ServiceRpcContexctInterceptor serviceRpcContexctInterceptor() {
        return new ServiceRpcContexctInterceptor();
    }

    @Bean
    public ServiceTraceContextInterceptor traceContextInterceptor() {
        return new ServiceTraceContextInterceptor();
    }

    private static class FeignClinetExcludeMappingHandlerMapping extends RequestMappingHandlerMapping {
        @Override
        protected boolean isHandler(Class<?> beanType) {
            return super.isHandler(beanType) && !AnnotatedElementUtils.hasAnnotation(beanType, FeignClient.class);
        }
    }

}
